package com.ideaction.service;

import com.ideaction.entity.giftcode.CodePool;
import com.ideaction.entity.giftcode.CodeUse;
import com.ideaction.entity.giftcode.GiftGroup;
import com.ideaction.entity.giftcode.UseCodeBean;
import com.ideaction.game.utils.Localization;
import com.ideaction.globalconst.NoticeKeyConst;
import com.ideaction.globalconst.ParamKey;
import com.ideaction.globalconst.Result;
import com.ideaction.req.PlayerCommonReqBody;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class GiftCodeService {
    
    private String lock_name = "GIFTCODE_LOCK";
    
    @Autowired
    private MongoTemplate funcMongoTemplate;
    
    @Autowired
    private RedissonClient redissonClient;
    
    public String useGiftCode(PlayerCommonReqBody playerCommonReqBody) {
        Result r = Result.build();
        String userId = playerCommonReqBody.getUserId();
        String giftCode = playerCommonReqBody.getParam(ParamKey.GIFTCODE);
        String language = playerCommonReqBody.getParam(ParamKey.LANGUAGE);
        giftCode = giftCode.toUpperCase();
        Query query = new Query();
        Criteria criteria = Criteria.where("codeId").is(giftCode);
        query.addCriteria(criteria);
        if (!funcMongoTemplate.exists(query, CodePool.class)) {
            log.info("无效的激活码  code:" + giftCode + "userId:" + userId);
            r.put("Result", false);
            r.put("Notice", Localization.getInstance().get(NoticeKeyConst.GIFT_CODE_NOT_AVALIABLE, language));
            return r.response();
        }
        //对激活码数量的使用过程加锁,在分布式环境中,如果不加锁,会出现一码多用,或者超量情况
        String item = null;
        RLock lock = redissonClient.getLock(lock_name);
        try {
            //默认30秒过期,这里设置15秒
            lock.tryLock(15, TimeUnit.SECONDS);
            item = useCode(r, query, playerCommonReqBody);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        } finally {
            lock.unlock();
        }
        // 礼包码操作完毕,这里处理钻石奖励 //TODO 处理需要服务器保存的资源
        if (StringUtils.isNotEmpty(item)) {
        
        }
        return r.response();
    }
    
    private String useCode(Result r, Query query, PlayerCommonReqBody playerCommonReqBody) {
        String userId = playerCommonReqBody.getUserId();
        String giftCode = playerCommonReqBody.getParam(ParamKey.GIFTCODE);
        String language = playerCommonReqBody.getParam(ParamKey.LANGUAGE);
        String channel = playerCommonReqBody.getParam(ParamKey.CHANNEL);
        
        CodePool codePool = funcMongoTemplate.findOne(query, CodePool.class);
        // 否则判断总共次数
        if (codePool.getUseCount() >= codePool.getTotalCount()) {
            log.info("该激活码次数已经用完,totalCount:" + codePool.getTotalCount() + " useCount:" + codePool.getUseCount()
                    + " code:" + giftCode);
            r.put("Result", false);
            r.put("Notice", Localization.getInstance().get(NoticeKeyConst.GIFT_CODE_COUNT_OVER, language));
            return null;
        }
        // 组条件判断
        Query queryGroup = new Query();
        Criteria criteriaGroup = Criteria.where("groupId").is(codePool.getGroupId());
        queryGroup.addCriteria(criteriaGroup);
        GiftGroup giftGroup = funcMongoTemplate.findOne(queryGroup, GiftGroup.class);
        if (giftGroup == null) {
            log.info("激活码没有对应分组信息,code:" + giftCode + "userId:" + userId);
            r.put("Result", false);
            r.put("Notice", Localization.getInstance().get(NoticeKeyConst.GIFT_CODE_NOT_AVALIABLE, language));
            return null;
        }
        //渠道判断
        List<String> channelList = giftGroup.getChannelList();
        if (!channelList.isEmpty() && !channelList.contains(channel)) {
            log.info("不满足渠道限制 code:" + giftCode + "userId:" + userId + " codechannel:" + channel + " userchannel:"
                    + channel);
            r.put("Result", false);
            r.put("Notice", Localization.getInstance().get(NoticeKeyConst.GIFT_CODE_LIMITED_2, language));
            return null;
        }
        //判断礼包码所属组的数量限制
        if (giftGroup.getUseCount() >= giftGroup.getTotalCount()) {
            log.info("该激活码所属的组次数已经用完,totalCount:" + giftGroup.getUseCount() + " useCount:" + giftGroup.getUseCount()
                    + " code:" + giftCode);
            r.put("Result", false);
            r.put("Notice", Localization.getInstance().get(NoticeKeyConst.GIFT_CODE_COUNT_OVER, language));
            return null;
        }
        // 判断用户领取情况
        CodeUse codeUse = funcMongoTemplate.findById(userId, CodeUse.class);
        if (codeUse == null) {
            codeUse = new CodeUse(userId);
        } else {
            if (codeUse.getUsedCodeList().stream().filter(e -> e.getCode().equalsIgnoreCase(codePool.getCodeId()))
                    .findAny().isPresent()) {
                //已经使用过
                r.put("Result", false);
                r.put("Notice", Localization.getInstance().get(NoticeKeyConst.GIFT_CODE_HAVE_REWARD, language));
                return null;
            }
        }
        codeUse.getUsedCodeList().add(new UseCodeBean(giftCode, codePool.getGroupId()));
        // 礼包码计数
        codePool.setUseCount(codePool.getUseCount() + 1);
        // 组计数
        giftGroup.setUseCount(giftGroup.getUseCount() + 1);
        // 保存领取记录
        funcMongoTemplate.save(codeUse);
        // 更新礼包码计数
        funcMongoTemplate.save(codePool);
        // 更新组计数
        funcMongoTemplate.save(giftGroup);
        log.info("用户成功领取礼包码," + "userId:" + userId + "code:" + giftCode);
        return codePool.getItem();
    }
}
